/*
 * Created on Apr 18, 2004
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
package org.wiztools.te;

import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;

import org.wiztools.te.exception.TEWarnException;
import org.wiztools.te.DirectoryConstants;

/**
 * @author subhash
 *
 * To change the template for this generated type comment go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
public final class TEPluginLoader{
	private static TEPluginLoader loader;
	
	// For dynamic path creation of plugin folders
	private static final String fileSeparator = System.getProperty("file.separator");
	
	private ClassLoader libCl;
	private ClassLoader pluginCl;
	
	// Singleton
	private TEPluginLoader(){
		
	}
	
	public static TEPluginLoader getInstance(){
		if(loader==null){
			synchronized(TEPluginLoader.class){
				if(loader==null){
					loader = new TEPluginLoader();
				}
			}
		}
		return loader;
	}
	
	private URL[] getPlugins(String dir) throws MalformedURLException{
		File d = new File(dir);
		Collection<URL> c = new ArrayList<URL>();
		if(d.exists() && d.canRead() && d.isDirectory()){
			File[] arr = d.listFiles(new TEJarFilenameFilter());
			for(int i=0;i<arr.length;i++){
				c.add(arr[i].toURL());
			}
			int len = c.size();
			URL[] urls = new URL[c.size()];
			int i = 0;
			for(URL url: c){
				urls[i] = url;
				i++;
			}
			return urls;
		}
		return null;
	}
	
	private void loadClassLoaders() throws MalformedURLException{
		// The immediate parent CL
		ClassLoader previous = null;
		
		ClassLoader cl = this.getClass().getClassLoader();
		previous = cl;
		
		URL[] t_urls = getPlugins(DirectoryConstants.LIB);

		if(t_urls != null){
			URL[] libClURL = new URL[t_urls.length+1];
		
			libClURL[0] = new File(DirectoryConstants.CLASSES).toURL();
			for(int i=0;i<t_urls.length;i++){
				libClURL[i+1] = t_urls[i];
			}
			// GC
			t_urls = null;
			libCl = new URLClassLoader(libClURL, previous);
			previous = libCl;
		}
		else{
			URL[] libClURL = new URL[1];
			libClURL[0] = new File(DirectoryConstants.CLASSES).toURL();
			libCl = new URLClassLoader(libClURL, previous);
			previous = libCl;
		}
		
		URL[] urls = getPlugins(DirectoryConstants.JAR_PLUGIN);
		if(urls!=null){
			pluginCl = new URLClassLoader(urls, previous);
		}
	}
	
	public Class getPluginClass(String classNme) throws TEWarnException{
		if(libCl == null){
			try{
				loadClassLoaders();
			}
			catch(MalformedURLException mue){
				throw new TEWarnException("Could not find class: "+classNme);
			}
		}
		
		Class c = null;
		try{
			if(pluginCl!=null){
				c = pluginCl.loadClass(classNme);
			}
			else{
				c = this.getClass().getClassLoader().loadClass(classNme);
			}
		}
		catch(ClassNotFoundException cnfe){
			throw new TEWarnException("ClassNotFound: "+classNme);
		}
		return c;
	}
	
	public ClassLoader getLibraryClassLoader() throws MalformedURLException{
		if(libCl == null){
			loadClassLoaders();
		}
		return libCl;
	}
	
	class TEJarFilenameFilter implements FilenameFilter{
		public boolean accept(File dir, String name){
			if(name.matches("^.*\\.[jJ][aA][rR]$")){
				return true;
			}
			return false;
		}
	}
}
